home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / dp / dp_val.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  4.7 KB  |  222 lines

  1. /* 
  2. ** Three functions which extract a double-precision numeric value 
  3. ** from a string.
  4. ** Copyright (C) 1998 David Benn
  5. ** 
  6. ** This program is free software; you can redistribute it and/or
  7. ** modify it under the terms of the GNU General Public License
  8. ** as published by the Free Software Foundation; either version 2
  9. ** of the License, or (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15.  
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with this program; if not, write to the Free Software
  18. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.    
  20.    -- void dp_val(double *,char *) --
  21.  
  22.    Since Sozobon C doesn't support doubles, we use an array of
  23.    2 long values instead.
  24.  
  25.    Converts a string into a double-precision floating point value. 
  26.  
  27.    The string must contain a number of the following format:
  28.  
  29.     [+|-][.]nnn[.nnn][e|E[+|-]nnn]
  30.  
  31.     eg:     1234
  32.         12.25
  33.         -.12
  34.         1.5e+10    
  35.  
  36.    In other words, any legal AmigaBASIC integer or single-precision literal.
  37.  
  38.    This source was based upon code for VAL (see dates prior to October 1996).
  39.  
  40.    -------------------------------
  41.    Author: David J Benn
  42.      Date: 19th,24th January 1993,
  43.        14th,16th February 1993,
  44.        23rd January 1994,
  45.        5th June 1994,
  46.        17th,18th October 1996
  47.    -------------------------------
  48. */
  49.  
  50. #define BOOL     short
  51. #define BYTE     char
  52.  
  53. #define TRUE     (1L)
  54. #define FALSE     (0L)
  55. #define EOS    '\0'
  56.  
  57. /* global variables */
  58. char     ch;    
  59. long    cc;
  60.  
  61. /* IEEE DP math library bases */
  62. extern    long     MathIeeeDoubBaseBase;
  63. extern    long     MathIeeeDoubTransBase;
  64.  
  65. /* IEEE DP math functions */
  66. void    dp_longint_to_double();
  67. void    dp_add();
  68. void    dp_div();
  69. void    dp_mul();
  70. void    dp_pow();
  71.  
  72. /* functions */
  73. void nextch(str)
  74. char *str;
  75. {
  76.  /* retrieve next character from string. */
  77.  
  78.     ch = str[cc++];
  79. }
  80.  
  81. void dp_val(doubleval,str)
  82. long    doubleval[2];
  83. char     *str;
  84. {
  85. long     i;
  86. long     n[2];
  87. long     index;
  88. long     periods;
  89. long    placecount;
  90. long     places;
  91. long    ex;
  92. long     ex_sign;
  93. BOOL    period;
  94. long     sign;
  95. long    a[2],b[2],c[2],d[2],e[2];
  96.  
  97.   /* zero double value */
  98.   doubleval[0] = doubleval[1] = 0;
  99.  
  100.   /* start of string */
  101.   cc=0;
  102.  
  103.   /* convert str to double */
  104.   nextch(str);
  105.   while (ch <= ' ' && ch != EOS) nextch(str);  /* skip leading whitespace */
  106.  
  107.   /* + | - */
  108.   switch(ch)
  109.   {
  110.    case '-' :     sign = -1; nextch(str); 
  111.         break;
  112.   
  113.    case '+' :    sign = 1; nextch(str);
  114.         break;
  115.  
  116.    default  :    sign = 1; 
  117.   }
  118.  
  119.   if ((ch >= '0' && ch <= '9') || ch == '.')
  120.   {
  121.    n[0]=n[1]=0;
  122.    index=0;
  123.    period=FALSE;
  124.    periods=0;
  125.    placecount=0;
  126.    
  127.    /* is first char '.'? */
  128.    if (ch == '.')
  129.    {
  130.     period=TRUE;
  131.     placecount=0;
  132.     index=1;
  133.     periods++;
  134.    }
  135.  
  136.    /* get the value */
  137.    if (!period) n[0]=10*n[0]+(ch-'0');
  138.  
  139.    do
  140.    {
  141.     nextch(str);
  142.     if (ch >= '0' && ch <= '9') n[index]=10*n[index]+(ch-'0');
  143.     if ((ch >= '0' && ch <= '9') && period) placecount++;
  144.     if (ch == '.') periods++;
  145.     if ((ch == '.') && (!period))
  146.     {
  147.      period=TRUE;
  148.      placecount=0;
  149.      index=1;
  150.     }
  151.    }
  152.    while (((ch >= '0' && ch <= '9') || ch == '.') && (periods <= 1));
  153.  
  154.    /* integer or real? */
  155.    if (period && periods == 1)
  156.    {
  157.     /* make DP */
  158.     places=1;
  159.     for (i=1;i<=placecount;i++) places *= 10;
  160.  
  161.     /* integer component */
  162.     dp_longint_to_double(a,n[0]);
  163.  
  164.     /* fractional component */    
  165.     dp_longint_to_double(b,n[1]);
  166.     dp_longint_to_double(c,places);
  167.     dp_div(d,b,c);
  168.  
  169.     /* DP value */
  170.     dp_add(doubleval,a,d);
  171.    }  
  172.    else 
  173.       dp_longint_to_double(doubleval,n[0]);
  174.  
  175.    /* is it a real in exponential form? */
  176.    if (ch == 'E' || ch == 'e')
  177.    {
  178.     ex=0;
  179.     ex_sign=1;
  180.  
  181.     nextch(str);
  182.  
  183.     if (ch == '+') { ex_sign=1; nextch(str); }
  184.     else
  185.     if (ch == '-') { ex_sign=-1; nextch(str); }
  186.     
  187.     /* expected a digit so just return 0 */ 
  188.     if (ch < '0' || ch > '9') { doubleval[0] = doubleval[1] = 0; return; }
  189.  
  190.     /* get digits */
  191.     while (ch >= '0' && ch <= '9') { ex = 10*ex+(ch-'0'); nextch(str); }
  192.     ex *= ex_sign;
  193.  
  194.     /* convert to DP */
  195.     if (ex >= -308 && ex <= 307)    /* IEEE DP exponent limits as per RKM: Libraries */
  196.     {
  197.      /* if exponent is zero then doubleval=doubleval*1 since 10^0 = 1 */
  198.      if (ex != 0) 
  199.      {
  200.      /* n * 10^ex */
  201.      dp_longint_to_double(a,10);
  202.      dp_longint_to_double(b,ex);
  203.      dp_pow(c,a,b);
  204.      dp_mul(d,c,doubleval);
  205.      doubleval[0] = d[0]; doubleval[1] = d[1]; 
  206.      }
  207.     }
  208.     else
  209.      doubleval[0] = doubleval[1] = 0;
  210.    }
  211.   }
  212.   else
  213.     doubleval[0] = doubleval[1] = 0;
  214.  
  215.   /* positive or negative? */
  216.   if (sign == -1)
  217.   {
  218.     dp_neg(b,doubleval);
  219.       doubleval[0] = b[0]; doubleval[1] = b[1];
  220.   }
  221.